import axios from "axios";
import qs from "qs";
const CancelToken = axios.CancelToken;

const service = axios.create({
  timeout: 30000, // 请求超时时间 30s
});

const requestList = new Map(); // 存放当前请求未结束列表 key: 请求拼接字符串 , value:当前请求对应的 canel (取消)函数

// 根据 url method params data 生成唯一字符串
const createRequestId = (config) => {
  const { method, url, params, data } = config;
  return [method, url, qs.stringify(params), qs.stringify(data)].join("&");
};

// 添加请求到请求列表中
const addRequest = (config) => {
  const requestKey = createRequestId(config);
  config.cancelToken =
    config.cancelToken ||
    new CancelToken((cancel) => {
      if (!requestList.has(requestKey)) {
        requestList.set(requestKey, cancel);
      }
    });
};

// 移除并取消请求
const removeRequest = (config) => {
  const requestKey = createRequestId(config);
  if (requestList.has(requestKey)) {
    const cancelFn = requestList.get(requestKey);
    cancelFn();
    requestList.delete(requestKey);
  }
};

// 设置请求头
const setHeaders = (config) => {
  const headers = {
    accessToken: sessionStorage.getItem("token"),
    ...config.headers,
  };
  config.headers = headers;
};

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    setHeaders(config); // 设置请求头
    removeRequest(config); // 检查是否存在重复请求 ，存在则取消
    addRequest(config); // 当前请求添加到请求列表

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    const { config } = response;
    removeRequest(config); // 从请求列表中移除当前请求

    // 将后端返回的数据返回给 responce
    const { data } = response;
    return data;
  },
  (error) => {
    removeRequest(error.config || {}); // 从请求列表中移除当前请求
    return Promise.reject(error);
  }
);

export default service;